package com.ptswitch.material.model.contract;

import java.math.BigDecimal;

import javax.validation.constraints.Size;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.tapestry5.beaneditor.DataType;
import org.hxzon.project.BaseEntity;
import org.hxzon.tapestry5.util.TapestryEx;
import org.hxzon.util.BigDecimalUtil;

import com.ptswitch.material.model.material.Material;

public class ContractItem extends BaseEntity implements Comparable<ContractItem> {

    private static final long serialVersionUID = 5156788179539859892L;

    private Contract contract;

    @Size(max = DefineSize32)
    private String contractCode;

    private Material material;

    @Size(max = DefineSize32)
    private String code;// 物料编码

    @Size(max = 64)
    private String name;// 物料名称

    @Size(max = DefineSize2048)
    private String specification;// 规格型号

    @Size(max = DefineSize2048)
    private String footprint;// 器件封装

    @Size(max = DefineSize2048)
    private String brand;// 品牌

    // @Column(columnDefinition="varchar(2048) default ''")
    // @Validate("maxlength=64")
    // private String supplier;//供货商

    @Size(max = DefineSize2048)
    private String pcbDecal;// pcb封装

    @Size(max = DefineSize2048)
    private String remark;// 备注

    private int quantities;// 购买数量

    @Size(max = DefineSize32)
    private String measuringUnit;// 单位名称

    @DataType(TapestryEx.DataType_currency)
    private BigDecimal unitPriceIncludingTax = BigDecimalUtil.Int0;// 含税单价

    @DataType(TapestryEx.DataType_currency)
    private BigDecimal taxRate = BigDecimalUtil.Int0;// %

    @DataType(TapestryEx.DataType_currency)
    private BigDecimal unitPrice = BigDecimalUtil.Int0;// 单价 unitPriceIncludingTax=unitPrice*(1+taxRate/100)

    @DataType(TapestryEx.DataType_currency)
    private BigDecimal totalPrice = BigDecimalUtil.Int0;// 总价 unitPriceIncludingTax*quantities

    @DataType(TapestryEx.DataType_currency)
    private BigDecimal receivingPrice = BigDecimalUtil.Int0;

    @Size(max = DefineSize32)
    @DataType(TapestryEx.DataType_daytime)
    private String receivingDate;

    private int numReceiving;// 交货情况

    @Size(max = DefineSize2048)
    private String receivingRemark;

    @Size(max = DefineSize32)
    @DataType(TapestryEx.DataType_daytime)
    private String examineDate;

    private int numPass;

    private int numUnPass;

    @Size(max = DefineSize2048)
    private String examineRemark;

    // logic//FIXME
    public synchronized void computePrice() {
        //when modify unitPriceIncludingTax,or quantities,or taxRate
        totalPrice = unitPriceIncludingTax.multiply(BigDecimalUtil.getBigDecimal(quantities));
        BigDecimal taxRateTmp = taxRate.divide(BigDecimalUtil.Int100).add(BigDecimalUtil.Int1);
        unitPrice = unitPriceIncludingTax.divide(taxRateTmp, BigDecimal.ROUND_HALF_EVEN);
        //when modify unitPriceIncludingTax,or numReceiving
        receivingPrice = unitPriceIncludingTax.multiply(BigDecimalUtil.getBigDecimal(numReceiving));
    }

    public void returnItem(int numReturn) {
        numReceiving = numReceiving - numReturn;
        //FIXME
        if (numUnPass >= numReturn) {
            numUnPass = numUnPass - numReturn;
            return;
        } else {
            numReturn = numReturn - numUnPass;
            numUnPass = 0;
            //un examine auto compute
            int unExamine = getNumUnExamine();
            if (unExamine < 0) {
                numPass = numPass + unExamine;
            }
        }
    }

    // get and set

    public Contract getContract() {
        return contract;
    }

    public void setContract(Contract contract) {
        this.contract = contract;
        this.contractCode = contract.getCode();
    }

    public String getContractCode() {
        return contractCode;
    }

    public void setContractCode(String contractCode) {
        this.contractCode = contractCode;
    }

    public Material getMaterial() {
        return material;
    }

    public void setMaterial(Material material) {
        this.material = material;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSpecification() {
        return specification;
    }

    public void setSpecification(String specification) {
        this.specification = specification;
    }

    public String getFootprint() {
        return footprint;
    }

    public void setFootprint(String footprint) {
        this.footprint = footprint;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public int getQuantities() {
        return quantities;
    }

    public void setQuantities(int quantities) {
        this.quantities = quantities;
    }

    public String getMeasuringUnit() {
        return measuringUnit;
    }

    public void setMeasuringUnit(String measuringUnit) {
        this.measuringUnit = measuringUnit;
    }

    public BigDecimal getUnitPriceIncludingTax() {
        return unitPriceIncludingTax;
    }

    public void setUnitPriceIncludingTax(BigDecimal unitPriceIncludingTax) {
        this.unitPriceIncludingTax = unitPriceIncludingTax;
    }

    public BigDecimal getTaxRate() {
        return taxRate;
    }

    public void setTaxRate(BigDecimal taxRate) {
        this.taxRate = taxRate;
    }

    public BigDecimal getUnitPrice() {
        return unitPrice;
    }

    public void setUnitPrice(BigDecimal unitPrice) {
        this.unitPrice = unitPrice;
    }

    public BigDecimal getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(BigDecimal totalPrice) {
        this.totalPrice = totalPrice;
    }

    public BigDecimal getReceivingPrice() {
        return receivingPrice;
    }

    public void setReceivingPrice(BigDecimal receivingPrice) {
        this.receivingPrice = receivingPrice;
    }

    public String getReceivingDate() {
        return receivingDate;
    }

    public void setReceivingDate(String receivingDate) {
        this.receivingDate = receivingDate;
    }

    public int getNumReceiving() {
        return numReceiving;
    }

    public void setNumReceiving(int numReceiving) {
        this.numReceiving = numReceiving;
    }

    public int getNumUnReceiving() {
        return this.quantities - this.numReceiving;
    }

    public boolean isReceivingOk() {
        return this.numReceiving == this.quantities;
    }

    public String getReceivingRemark() {
        return receivingRemark;
    }

    public void setReceivingRemark(String receivingRemark) {
        this.receivingRemark = receivingRemark;
    }

    public String getExamineDate() {
        return examineDate;
    }

    public void setExamineDate(String examineDate) {
        this.examineDate = examineDate;
    }

    public int getNumPass() {
        return numPass;
    }

    public void setNumPass(int numPass) {
        this.numPass = numPass;
    }

    public int getNumUnPass() {
        return numUnPass;
    }

    public void setNumUnPass(int numUnPass) {
        this.numUnPass = numUnPass;
    }

    public int getNumUnExamine() {
        return this.numReceiving - this.numPass - this.numUnPass;
    }

    public int getNumUnPassAndUnExamine() {
        return this.numReceiving - this.numPass;
    }

    public boolean isPassOk() {
        return numPass == this.numReceiving;
    }

    public boolean isExamineOk() {
        return getNumUnExamine() == 0;
    }

    public String getExamineRemark() {
        return examineRemark;
    }

    public void setExamineRemark(String examineRemark) {
        this.examineRemark = examineRemark;
    }

    public String getPcbDecal() {
        return pcbDecal;
    }

    public void setPcbDecal(String pcbDecal) {
        this.pcbDecal = pcbDecal;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    @Override
    public String toString() {
        return this.code + "[" + this.name + "]" + this.specification + ";品牌:" + this.brand;
    }

    public String print() {
        StringBuilder sb = new StringBuilder();
        sb.append("code:").append(code).append(",name:").append(name).append(",spec:").append(specification).append(",footprint:").append(footprint).append(",brand:").append(brand).append(",desc:")
                .append(",supplier:")// .append(supplier)
                .append(",pcbDecal:").append(pcbDecal).append(",tmpCode:").append(",remark:").append(remark);
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (!(o instanceof ContractItem)) {
            return false;
        }
        ContractItem other = (ContractItem) o;
        return new EqualsBuilder().append(this.code, other.getCode()).isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(this.code).toHashCode();
    }

    @Override
    public int compareTo(ContractItem o) {
        return this.code.compareTo(o.getCode());
    }

    //----transient for form-----------------------
    private transient int numCurrentReceive = -1;
    private transient int numCurrentPass = -1;
    private transient int numCurrentUnPass = -1;
    private transient int numCurrentReturn = -1;
    private transient String errorMsg;

    public int getNumCurrentReceive() {
        if (numCurrentReceive != -1) {
            return numCurrentReceive;
        }
        return this.getNumUnReceiving();//max
    }

    public void setNumCurrentReceive(int currentReceive) {
        this.numCurrentReceive = currentReceive;
    }

    public int getNumCurrentPass() {
        if (numCurrentPass != -1) {
            return numCurrentPass;
        }
        return this.getNumUnExamine();//max
    }

    public void setNumCurrentPass(int numCurrentPass) {
        this.numCurrentPass = numCurrentPass;
    }

    public int getNumCurrentUnPass() {
        if (numCurrentUnPass != -1) {
            return numCurrentUnPass;
        }
        return 0;//max=this.getNumUnExamine();
    }

    public void setNumCurrentUnPass(int numCurrentUnPass) {
        this.numCurrentUnPass = numCurrentUnPass;
    }

    public int getNumCurrentReturn() {
        if (numCurrentReturn != -1) {
            return numCurrentReturn;
        }
//		return this.getNumUnExamine() + this.getNumUnPass();//max
        return this.getNumUnPass();
    }

    public void setNumCurrentReturn(int numCurrentReturn) {
        this.numCurrentReturn = numCurrentReturn;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

}
